<?php
class JsonFormatValidator {

  /**
   * Validates the value calling a method named 'validate'.ucfirst($format) in this intance.
   * If the method does not exists it will throw a runtime error.
   *
   * @param the value to be validated $value
   * @param the format $format
   * @return false/string returns false if it validates ok, or a string with the error message.
   */
  function validate($value,$format) {
    $formatNotSupportedMessage = "The format %s is not supported by the format validator: %s";
    $method = 'validate'. str_replace(' ','',ucwords(str_replace('-',' ',$format)));
    if(!method_exists($this,$method)) {
      throw new JsonSchemaFormatNotSupportedException(
      sprintf($formatNotSupportedMessage,$format,get_class($this))
      );
    }
    return $this->$method($value);
  }

  /**
   * @return JsonFormatValidator
   */
  static function build() {
    return new JsonFormatValidator();
  }

  /**
   * @return false/string returns false if it validates ok, or a string with the error message.
   */
  function validateEmail($value) {
    $errorMessage = " is not a valid email";
    if(!is_string($value) || $value == '') {
      return $errorMessage;
    }
    $e = eregi("^[[:alnum:]][a-z0-9_.-]*@[a-z0-9.-]+\.[a-z]{2,4}$", $value);
    if ($e)
    {
      return false;
    }
    else return $errorMessage;
  }

  /**
   * Validate text in constant format CONSTANT_NAME
   *
   * @param string $value
   * @return false/string returns false if it validates ok, or a string with the error message.
   */
  function validateConstant($value) {
    $errorMessage = " is not a valid format";

    if (preg_match("/^[A-Z_]$/", $value))
      return false;

    return $errorMessage;
  }

  /**
   * Validate date time value in ISO 8601 specific format YYYY-MM-DD hh:mm:ss +-hh:mm
   *
   * @param  string $value The date time value
   * @return false/string returns false if it validates ok, or a string with the error message.
   */
  function validateDateTime($value) {
    $errorMessage = " is not a valid datetime";

    if (preg_match("/^(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})([\+-](\d{2}):(\d{2}))?$/", $value, $matches)) {
      if ($matches[1].$matches[2].$matches[3] == '00000000' || checkdate($matches[2], $matches[3], $matches[1])) {
        if ($matches[4] <= 23 && $matches[5] <= 59 && $matches[6] <= 59) {
          if (isset($matches[7])) {
            if ($matches[8] <= 12 && $matches[9] <= 59) {
              return false;
            }
          } else return false;
        }
      }
    }
    return $errorMessage;
  }

  /**
   * Validate date value de in ISO 8601 specific format YYYY-MM-DD.
   *
   * @param  string $value The date value
   * @return false/string returns false if it validates ok, or a string with the error message.
   */
  function validateDate($value) {
    $errorMessage = " is not a valid date";

    if (preg_match('/^(\d{4})-(\d{2})-(\d{2})$/', $value, $matches)) {
      if ($matches[1].$matches[2].$matches[3] == '00000000' || checkdate($matches[2], $matches[3], $matches[1])) {
        return false;
      }
    }

    return $errorMessage;
  }

  /**
   * Validate date value in ISO 8601 specific hh:mm:ss
   * AM|PM time format is not allowed
   *
   * @param  string $value The time value
   * @return false/string returns false if it validates ok, or a string with the error message.
   */
  function validateTime($value) {
    $errorMessage = " is not a valid time";

    if (preg_match('/^(\d{2}):(\d{2}):(\d{2})$/', $value, $matches)) {
      if ($matches[1] <= 23 && $matches[2] <= 59 && $matches[3] <= 59) {
        return false;
      }
    }
    return $errorMessage;
  }

  /**
   * Validate hexadecimal color value.
   *
   * @param  string $value The color value
   * @return false/string returns false if it validates ok, or a string with the error message.
   */
  function validateColor($value) {
    $errorMessage = " is not a valid color";

    if (preg_match("/^#?([a-f]|[A-F]|[0-9]){3}(([a-f]|[A-F]|[0-9]){3})?$/", $value))
    return false;

    return $errorMessage;
  }

  /**
   * Validate a phone number in format E.123
   *
   * @param string $value
   * @return false/string returns false if it validates ok, or a string with the error message.
   */
  function validatePhone($value) {
    $errorMessage = " is not a valid phone number";

    if (preg_match("/^(\(0?[0-9]{2}\) \d{3,4}\s?\d{4}|\+\d{2} \d{2} \d{3,4}\s?\d{4})$/", $value))
    return false;

    return $errorMessage;
  }

  /**
   * Validate a url address
   *
   * @param string $value
   * @return false/string returns false if it validates ok, or a string with the error message.
   */
  function validateUrl($value) {
    $errorMessage = " is not a valid url";

    if (eregi("^(https?|ftp)\:\/\/([a-z0-9+!*(),;?&=\$_.-]+(\:[a-z0-9+!*(),;?&=\$_.-]+)?@)?[a-z0-9+\$_-]+(\.[a-z0-9+\$_-]+)*(\:[0-9]{2,5})?(\/([a-z0-9+\$_-]\.?)+)*\/?(\?[a-z+&\$_.-][a-z0-9;:@/&%=+\$_.-]*)?(#[a-z_.-][a-z0-9+\$_.-]*)?\$", $value))
    return false;

    return $errorMessage;
  }

  /**
   * Validate a ip address
   *
   * @param string $value
   * @return false/string returns false if it validates ok, or a string with the error message.
   */
  function validateIpAddress($value) {
    $errorMessage = " is not a valid ip address";

    if (preg_match("/^\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b$/", $value))
    return false;

    return $errorMessage;
  }
}
?>